/**
 * @file ConfigVal.h
 * @author  haifeng (haifengxiao@icloud.com)
 * @brief 
 * @version 0.1
 * @date 2021-07-08
 * 
 * @copyright Copyright (c) 2021
 * 
 */

#pragma once

#include <exception>
#include <functional>
#include <stdint.h>

#include "Logger.h"
#include "LoggerManager.h"
#include "ConfigValBase.h"

namespace Chen{
namespace Conf{

template <typename T>
class ConfigVal : public ConfigValBase
{
public:
    typedef std::shared_ptr<ConfigVal> ptr;
    typedef std::function<void (const T& old_value,T& new_value)> on_change_cb;
    /**
     * @brief Construct a new Config Val object
     * 
     * @param name 
     * @param default_val 
     * @param description 
     */
    ConfigVal(const std::string &name, const T &default_val, const std::string &description = "")
        : ConfigValBase(name, description), m_val(default_val)
    {
    }

    /**
     * @brief 将类型转换成字符串
     * 
     * @return std::string 
     */
    std::string toString() override
    {
        try
        {
            return boost::lexical_cast<std::string>(m_val);
        }
        catch (std::exception e)
        {
            CHEN_LOG_ERROR(CHEN_LOG_ROOT()) << "ConfigVal::toString exception"
                                            << e.what()
                                            << "convert:"
                                            << typeid(m_val).name()
                                            << "to string";
        }
        return "";
    }

    /**
     * @brief 从字符串转成相应的类型
     * 
     * @param val 
     * @return true 转换成功
     * @return false 转换失败
     */
    bool fromString(const std::string &val) override
    {
        try
        {
            return boost::lexical_cast<T>(m_val);
        }
        catch (std::exception e)
        {
            CHEN_LOG_ERROR(CHEN_LOG_ROOT()) << "ConfigVal::fromString exception"
                                            << e.what() << "convert string to"
                                            << typeid(m_val).name();
        }
        return false;
    }

    /**
     * @brief Get the Value object
     * 
     * @return const T 
     */
    const T getValue() const { return m_val; }

    /**
     * @brief Set the Value object
     * 
     * @param val 
     */
    void setValue(const T &val) { 
        if(val == m_val){
            return ;
        }
        for(auto & i : m_cbs){
            i.second(m_val,val);
        }
        m_val = val;
    } 
    
    /**
     * @brief 添加监听
     *
     */
    void addListenser(uint64_t key,on_change_cb &cb){
        m_cbs[key] = cb;
    }

    void delListener(uint64_t key){
        m_cbs.erase(key);
    }

    on_change_cb getListener(uint64_t key){
        auto it = m_cbs.find(key);
        return it == m_cbs.end() ? nullptr : it->second;
    }

    void clearListener(){
        m_cbs.clear();
    }
private:
    T m_val;
    // 变更回调函数，uint_64 key 要求唯一，一般可用hash
    std::map<uint64_t,on_change_cb> m_cbs;
};

}//namespace Conf
}//namespace Chen
